package com.weavernorth.attendance;

import com.engine.kq.biz.KQBalanceOfLeaveBiz;
import com.engine.kq.biz.KQGroupMemberComInfo;
import com.engine.kq.biz.KQLeaveRulesBiz;
import com.engine.kq.enums.DurationTypeEnum;
import com.engine.kq.util.KQDurationCalculatorUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import weaver.common.DateUtil;
import weaver.conn.RecordSet;
import weaver.general.BaseBean;

import weaver.general.Util;
import weaver.hrm.User;
import weaver.hrm.resource.ResourceComInfo;
import weaver.systeminfo.SystemEnv;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: ecology_erdos
 * @description: 自动扣假执行sql类
 * @author: zm
 * @create: 2019-12-12 09:34
 **/


public class AttendUtil extends BaseBean {
    public static Log log = LogFactory.getLog(AttendUtil.class.getName());


    //扣假方法
    public void leaveDeduct() {
        //数据库操作
        RecordSet rsSelectMode = new RecordSet();
        RecordSet rsUp = new RecordSet();
        //请假工具类
        AttendUtil attendUtil = new AttendUtil();
        //当前日期

        String strCurrentDate=DateUtil.getCurrentDate();
        //更新人员id到建模表,用于报表查询
        //  rsUp.executeQuery("update uf_kjgn  set rymc=(select id from hrmresource where uf_kjgn.ygh=workcode)");
        //1.查询扣假建模表中需扣假的人员信息 uf_kjgn 扣假信息通过扣假日期和员工号确定唯一
        //String strLeaveSql = "select uf.id,uf.ygh,uf.kjrq,uf.dxkct,uf.njkct,uf.sfyqj,uf.sykjts ,hr.id hrid from uf_kjgn  uf,HrmResource hr where uf.ygh=hr.workcode and (uf.sfywckj='1' or uf.sfywckj is null) and uf.id in ('"+strIds+"') order by uf.kjrq";
        String strLeaveSql = "select uf.id,uf.ygh,uf.kjrq,uf.dxkct,uf.njkct,uf.sfyqj,uf.sykjts ,hr.id hrid from uf_kjgn  uf,HrmResource hr where uf.ygh=hr.workcode and (uf.sfywckj='1' or uf.sfywckj is null)  order by uf.kjrq";
        log.info("得到扣假建模信息:" + strLeaveSql);
        rsSelectMode.execute(strLeaveSql);
        while (rsSelectMode.next()) {
            //剩余的扣假天数
            Double douSyts = 0.00;
            //标识是否扣除完成
            String strComplete = "false";
            //建模表id
            String strId = Util.null2String(rsSelectMode.getString("id"));
            //员工号
            String strUserCode = Util.null2String(rsSelectMode.getString("ygh"));
            //员工id
            String strUserid = Util.null2String(rsSelectMode.getString("hrid"));

            //扣假日期
            String strKjrq = Util.null2String(rsSelectMode.getString("kjrq"));
            //剩余扣假天数
            String strSykjts = Util.null2String(rsSelectMode.getString("sykjts"));
            if (!"".equals(strSykjts)) {
                douSyts = Double.parseDouble(strSykjts);
            }
            //扣假逻辑开始
            //1.1.查询此员工是否请假,并得到请假时长
            Double douLeaveTime = attendUtil.deductDays(strUserid, strKjrq);
            log.info("得到的请假时长" + douLeaveTime);
            //如果有请假,则扣除请假
            if (douLeaveTime != 0) {
                if (!"".equals(strSykjts)) {
                    //剩余扣假天数 减去请假天数
                    douSyts = douSyts - douLeaveTime;
                    //更新建模表是否请假字段为  是
                    attendUtil.updateLeave(strId);
                    strComplete = "true";
                    //扣除完成后,小于0后置位0
                    if (douSyts < 0) {
                        douSyts = 0.0;
                    }
                }
            }
            log.info("请假流程扣除后剩余的扣假天数:" + douSyts);
            //1.2如果无请假或请假时长不够扣除,则继续扣除调休假
            if (douSyts > 0) {
                log.info("进入扣除调休假,人员id:" + strUserid);
                //查询有效的调休假 ruleid:5 为调休假
                log.info("日期参数:" + strKjrq);
                String strSyjq = KQBalanceOfLeaveBiz.getRestAmount(strUserid, "5", strKjrq);
                log.info("第一次得到有效的调休假:" + strSyjq);
                if (!"".equals(strSyjq) && Double.parseDouble(strSyjq) != 0) {
                    //调休扣除天数
                    Double douTxts = 0.0;
                    if (Double.parseDouble(strSyjq) < douSyts) {
                        douTxts = Double.parseDouble(strSyjq);
                    } else {
                        douTxts = douSyts;
                    }

                    log.info("调休扣除天数:" + douTxts);
                    //系统标准扣减逻辑
                    KQBalanceOfLeaveBiz.addUsedAmount(strUserid, strKjrq, "5", String.valueOf(douTxts), "", "", "");
                    log.info("扣假日期:" + strKjrq + ",执行扣假结束");
                    //扣除完成后,剩余扣除天数减去调休扣除
                    douSyts = douSyts - douTxts;
                    //扣除完成后,小于0后置位0
                    if (douSyts < 0) {
                        douSyts = 0.0;
                    }
                    //1.更新扣除调休的字段 值为 调休假剩余的天数 strSyjq
                    attendUtil.updateRest(strId, String.valueOf(douTxts));
                    strComplete = "true";

                }
            }
            log.info("当前还剩余未扣除的假:" + douSyts);

            //3 如果未扣除完继续扣除年假
            if (douSyts > 0) {
                log.info("继续扣除年假:" + douSyts);
                //查询有效的年假 ruleid:2 为年假
                String strSyjq = KQBalanceOfLeaveBiz.getRestAmount(strUserid, "2", strCurrentDate);
                log.info("有效年假时长:" + strSyjq);

                if (!"".equals(strSyjq) && Double.parseDouble(strSyjq) != 0) {
                    if(Double.parseDouble(strSyjq)>0){
                    //年假扣除天数
                    Double douNjts = 0.0;
                    if (Double.parseDouble(strSyjq) < douSyts) {
                        douNjts = Double.parseDouble(strSyjq);
                    } else {
                        douNjts = douSyts;
                    }
                    //系统标准扣减逻辑 ruid:2 为类型 年假
                    log.info("开始扣除年假:" + strSyjq + ",扣假日期:" + strKjrq);
                    KQBalanceOfLeaveBiz.addUsedAmount(strUserid, strKjrq, "2", String.valueOf(douNjts), "", "", "");
                    log.info("结束扣除年假");
                    //扣除完成后,减去扣除的年假天数
                    douSyts = douSyts - douNjts;
                    //扣除完成后,小于0后置位0
                    if (douSyts < 0) {
                        douSyts = 0.0;
                    }
                    //1.更新扣除年假的字段 值为 strSyjq
                    attendUtil.updateYear(strId, String.valueOf(douNjts));
                    strComplete = "true";
                    }
                }
            }

            log.info("年假扣除后剩余的带扣除的假:" + douSyts);

            //更新最终剩余未扣除的天数
            //是否已完成扣假,1为否,0为是
            String sfywckj = "1";
            //当最终剩余天数不等于开始剩余天数,此时完成扣假
            if (douSyts != Double.parseDouble(strSykjts) && douSyts == 0 && "true".equals(strComplete)) {
                sfywckj = "0";
            }
            log.info("当前剩余的扣假天数:" + douSyts);
            log.info("是否已完成扣假:" + sfywckj);
            //更新最终剩余扣假天数
            if ("true".equals(strComplete)) {
                attendUtil.updateRamin(strId, sfywckj, String.valueOf(douSyts));
            }


        }

    }


    /**
     * 得到请假的时长
     *
     * @param strUsercode
     * @param strLeaveDay
     * @return
     */
    public Double deductDays(String strUsercode, String strLeaveDay) {
        //基础类
        BaseBean bb = new BaseBean();
        //数据库操作
        RecordSet rsSelect = new RecordSet();
        //人员的请假时长共计
        Double douTime = 0.00;
        //请假流程表名
        String strTablename = "";
        //1.查询流程中是否存在请假数据
        //请假workflowid
        String strLeaveWorkflowid = bb.getPropValue("leaveMess", "leaveworkflowid");
        log.info("配置文件中请假workflowid" + strLeaveWorkflowid);
        //得到请假流程表
        rsSelect.execute("select tablename  from workflow_bill where id = (select formid from workflow_base where id='" + strLeaveWorkflowid + "' and isbill=1)");
        if (rsSelect.next()) {
            strTablename = Util.null2String(rsSelect.getString("tablename"));
        }
        //查询请假明细表中人员的请假时长,排除哺乳假,归档流程计算
        String strTimeSql = "select * from " + strTablename + " fm," + strTablename + "_dt1 fdt,workflow_requestbase wr where fm.requestid=wr.requestid and wr.currentnodetype='3' and fm.id=fdt.mainid and fdt.detail_resourceId='" + strUsercode + "' and detail_fromDate<='" + strLeaveDay + "' and detail_toDate>='" + strLeaveDay + "' and fdt.detail_newLeaveType!='12'";
        log.info("查询明细表请假时长sql:" + strTimeSql);
        rsSelect.executeQuery(strTimeSql);
        while (rsSelect.next()) {
            //请假类
            LeaveVo leaveVo = new LeaveVo();
            //开始日期
            String strBegindate = Util.null2String(rsSelect.getString("detail_fromDate"));
            leaveVo.setFromDate(strBegindate);
            //结束日期
            String strEnddate = Util.null2String(rsSelect.getString("detail_toDate"));
            leaveVo.setToDate(strEnddate);
            //开始时间
            String strBeginTime = Util.null2String(rsSelect.getString("detail_fromTime"));
            leaveVo.setFromTime(strBeginTime);
            //结束时间detail_toTime
            String strEndTime = Util.null2String(rsSelect.getString("detail_toTime"));
            leaveVo.setToTime(strEndTime);
            //请假人
            leaveVo.setUserId(strUsercode);
            //请假类型
            String strLeaveType = Util.null2String(rsSelect.getString("detail_newLeaveType"));
            leaveVo.setLeaveType(strLeaveType);
            //处理时长
            String countTime = Util.null2String(getSumTime(leaveVo, strLeaveDay));
            log.info("明细表中得到的请假时长:" + countTime);
            if (!"".equals(countTime)) {
                douTime = douTime + Double.parseDouble(countTime);
            }
        }

        log.info("最终得到的请假时长:" + douTime);
        return douTime;

    }


    public String getSumTime(LeaveVo leaveVo, String strLeaveDay) {
        String strSumtime = "";
        //对比开始结束日期和扣假日期;当开始日期与扣假日期相等,结束日期大于扣假日期时,则计算扣假日期当天的开始时间到扣假日期的23:59,得到扣假当天请假时长
        if ((strLeaveDay.compareTo(leaveVo.getFromDate()) == 0) && ((leaveVo.getToDate()).compareTo(strLeaveDay) > 0)) {
            leaveVo.setFromDate(strLeaveDay);
            leaveVo.setToDate(strLeaveDay);
            leaveVo.setToTime("23:59");
        }
        //对比开始结束日期和扣假日期;当结束日期与扣假日期相等,开始日期小于扣假日期时,则计算扣假日期当天的开始时间00:00到扣假日期的结束时间,得到扣假当天请假时长
        if (((leaveVo.getFromDate()).compareTo(strLeaveDay) < 0) && ((leaveVo.getToDate()).compareTo(strLeaveDay) == 0)) {
            leaveVo.setFromDate(strLeaveDay);
            leaveVo.setToDate(strLeaveDay);
            leaveVo.setFromTime("00:00");
        }
        if (((leaveVo.getFromDate()).compareTo(strLeaveDay) < 0) && ((leaveVo.getToDate()).compareTo(strLeaveDay) > 0)) {
            leaveVo.setFromDate(strLeaveDay);
            leaveVo.setToDate(strLeaveDay);
            leaveVo.setFromTime("00:00");
            leaveVo.setToTime("23:59");

        }
        //得到请假时长
        Map<String, String> mapTime = countTime(leaveVo);
        strSumtime = mapTime.get("duration");
        return strSumtime;
    }

    /**
     * 系统标准类:com.engine.kq.cmd.attendanceEvent.GetLeaveWorkDurationCmd
     * 中的计算方式;计算请假时长
     *
     * @return
     */
    public Map countTime(LeaveVo leaveVo) {
        BaseBean bb = new BaseBean();
        User user = new User();
        user.setLanguage(7);
        Map<String, Object> params = new HashMap<>();
        params.put("newLeaveType", leaveVo.getLeaveType());
        params.put("resourceId", leaveVo.getUserId());
        params.put("fromDate", leaveVo.getFromDate());
        params.put("toDate", leaveVo.getToDate());
        params.put("fromTime", leaveVo.getFromTime());
        params.put("toTime", leaveVo.getToTime());
        Map<String, Object> retmap = new HashMap<String, Object>();
        try {
            String newLeaveType = Util.null2String(params.get("newLeaveType"));
            bb.writeLog("当前请假类型" + newLeaveType);
            String resourceId = Util.null2String(params.get("resourceId"));
            bb.writeLog("当前resourceId:" + resourceId);
            String fromDate = Util.null2String(params.get("fromDate"));
            bb.writeLog("当前fromDate:" + fromDate);
            String toDate = Util.null2String(params.get("toDate"));
            bb.writeLog("当前toDate:" + toDate);
            String fromTime = Util.null2String(params.get("fromTime"));
            bb.writeLog("当前fromTime:" + fromTime);
            String toTime = Util.null2String(params.get("toTime"));
            bb.writeLog("当前toTime:" + toTime);
            ResourceComInfo rci = new ResourceComInfo();
            KQGroupMemberComInfo kqGroupMemberComInfo = new KQGroupMemberComInfo();
            String groupid = kqGroupMemberComInfo.getKQGroupId(resourceId, fromDate);
            if (resourceId.length() > 0 && groupid.length() == 0) {
                retmap.put("status", "-1");
                retmap.put("message", rci.getLastname(resourceId) + "," + fromDate + "没有设置考勤组，无法计算时长");
            }

            String durationrule = Util.null2String(KQLeaveRulesBiz.getMinimumUnit(newLeaveType));
            bb.writeLog("durationrule:" + durationrule);
            String computingMode = Util.null2String(KQLeaveRulesBiz.getComputingMode(newLeaveType));
            bb.writeLog("computingMode:" + computingMode);

            KQDurationCalculatorUtil kqDurationCalculatorUtil = new KQDurationCalculatorUtil.DurationParamBuilder(resourceId).
                    fromDateParam(fromDate).toDateParam(toDate).fromTimeParam(fromTime).toTimeParam(toTime).
                    newLeaveTypeParam(newLeaveType).durationRuleParam(durationrule).
                    computingModeParam(computingMode).durationTypeEnumParam(DurationTypeEnum.LEAVE).build();

            Map<String, Object> durationMap = kqDurationCalculatorUtil.getWorkDuration();


            for (String s : durationMap.keySet()) {
                bb.writeLog("key:" + s);
                bb.writeLog("values:" + durationMap.get(s));
            }

            retmap.put("duration", Util.null2String(durationMap.get("duration")));
            retmap.put("min_duration", Util.null2String(durationMap.get("min_duration")));
            retmap.put("status", "1");
        } catch (Exception e) {
            retmap.put("status", "-1");
            retmap.put("message", SystemEnv.getHtmlLabelName(382661, user.getLanguage()));
            bb.writeLog(e);
        }
        bb.writeLog("测试1duration:" + retmap.get("duration"));
        bb.writeLog("测试1min_duration:" + retmap.get("min_duration"));
        return retmap;
    }

    /**
     * 更新扣假建模表中是否请假字段为 "是"
     */

    public void updateLeave(String strId) {
        //数据库操作
        RecordSet rs = new RecordSet();
        String updateSql = "update uf_kjgn set sfyqj=0 where id=?";
        rs.executeQuery(updateSql, strId);
    }

    /**
     * 更新调休扣除天数字段值
     */
    public void updateRest(String strId, String strSyjq) {
        //数据库操作
        RecordSet rs = new RecordSet();
        String updateSql = "update uf_kjgn set dxkct=? where id=?";
        rs.executeQuery(updateSql, strSyjq, strId);
    }

    /**
     * 更新调休扣除天数字段值
     */
    public void updateYear(String strId, String strSyjq) {
        //数据库操作
        RecordSet rs = new RecordSet();
        String updateSql = "update uf_kjgn set njkct=? where id=?";
        rs.executeQuery(updateSql, strSyjq, strId);
    }

    /**
     * 更新剩余扣假天数和是否扣假完成
     */
    public void updateRamin(String strId, String strSfkjwc, String strSyts) {
        //数据库操作
        RecordSet rs = new RecordSet();
        //当前日期
        Date now = new Date();
        //设置日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        //格式化然后放入字符串中
        String createTime = dateFormat.format(now);
        String updateSql = "update uf_kjgn set sfywckj=?,sykjts=?,zhczrq=? where id=?";
        rs.executeQuery(updateSql, strSfkjwc, strSyts, createTime, strId);
    }

}
